package goUtils

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/md5"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/x509"
	"encoding/base64"
	"encoding/hex"
	"encoding/pem"
	"errors"
	"log/slog"
)

type MyUtils struct {
	Aes128Key  string
	Aes128Iv   string
	PublicKey  string
	PrivateKey string
}

// AES对称加密
func (c *MyUtils) EncryptAes128(str string) (s string) {
	defer func() {
		v := recover()
		if v != nil {
			slog.Error("recover", v)
			s = ""
		}
	}()
	block, err := aes.NewCipher([]byte(c.Aes128Key))
	if err != nil {
		panic(err.Error())
	}
	//填充内容，如果不足16位字符
	blockSize := block.BlockSize()
	originData := c._pad([]byte(str), blockSize)
	//加密方式
	blockMode := cipher.NewCBCEncrypter(block, []byte(c.Aes128Iv))
	//加密，输出到[]byte数组
	crypted := make([]byte, len(originData))
	blockMode.CryptBlocks(crypted, originData)
	return base64.StdEncoding.EncodeToString(crypted)
}

// AES对称解密
func (c *MyUtils) DecryptAes128(str string) (s string) {
	defer func() {
		v := recover()
		if v != nil {
			slog.Error("recover", v)
			s = ""
		}
	}()
	decode_data, err := base64.StdEncoding.DecodeString(str)
	if err != nil {
		panic(err.Error())
	}
	//生成密码数据块cipher.Block
	block, _ := aes.NewCipher([]byte(c.Aes128Key))
	//解密模式
	blockMode := cipher.NewCBCDecrypter(block, []byte(c.Aes128Iv))
	//输出到[]byte数组
	origin_data := make([]byte, len(decode_data))
	blockMode.CryptBlocks(origin_data, decode_data)
	//去除填充,并返回
	return string(c._unpad(origin_data))
}

func (c *MyUtils) _pad(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

func (c *MyUtils) _unpad(ciphertext []byte) []byte {
	length := len(ciphertext)
	//去掉最后一次的padding
	unpadding := int(ciphertext[length-1])
	return ciphertext[:(length - unpadding)]
}

// md5加密，16位或32位结果
func (c *MyUtils) MD5(str string, bit16 bool) string {
	hash := md5.New()
	hash.Write([]byte(str))
	str = hex.EncodeToString(hash.Sum(nil))
	if bit16 {
		return str[8:16]
	}
	return str
}

// sha1加密
func (c *MyUtils) Sha1(str string) string {
	_sha1 := sha1.New()
	_sha1.Write([]byte(str))
	return hex.EncodeToString(_sha1.Sum(nil))
}

// sha256加密
func (c *MyUtils) Sha256(data string) string {
	hash := sha256.New()
	hash.Write([]byte(data))
	return hex.EncodeToString(hash.Sum(nil))
}

// 非对称加密
func (c *MyUtils) RsaEncrypt(origData []byte) ([]byte, error) {
	//解密pem格式的公钥
	block, _ := pem.Decode([]byte(c.PublicKey))
	if block == nil {
		return nil, errors.New("public key error")
	}
	// 解析公钥
	pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	// 类型断言
	pub := pubInterface.(*rsa.PublicKey)
	//加密
	return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
}

// 非对称解密
func (c *MyUtils) RsaDecrypt(ciphertext []byte) ([]byte, error) {
	//解密
	block, _ := pem.Decode([]byte(c.PrivateKey))
	if block == nil {
		return nil, errors.New("private key error!")
	}
	//解析PKCS1格式的私钥
	priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	// 解密
	return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
}
